﻿using DataService.IService;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using DataService.Core.DataHelper;
using DataService.Core.ModeCode;
using DataService.Core.ServiceDTO;
using DataService.Core.Common;
using DataService.Core.Extensions;
using DataService.Cache.Data;
using System.Reflection;
using DataService.Data;

namespace DataService.Main
{
    public static class ModelDAL
    {
        private static readonly object _tableLocker = new object();
        private static readonly object _databaseLocker = new object();
        #region 创建数据模型
        /// <summary>
        /// 创建实体模型类
        /// </summary>
        /// <param name="modelCodePath">实体文件(.cs)的物理路径</param>
        /// <param name="sourceProvider"></param>
        /// <param name="tableNames">需要生成的实体名称(xxx.cs)</param>
        public static void CreateModelCodes(string modelCodePath, IDatabaseProvider sourceProvider, params string[] tableNames)
        {
            modelCodePath = Path.Combine(modelCodePath, sourceProvider.DBType.ToString() + "\\");
            var tables = FindAllTables(sourceProvider, tableNames);
            DataTable columns = DataTableHelper.ListToTable(tables.Columns);
            DataTable indexs = DataTableHelper.ListToTable(tables.Indexs);
            ModelCode modelCode = new ModelCode();
            modelCode.GenerateModel(columns, indexs, modelCodePath, sourceProvider.DBType.ToString());
            Console.WriteLine("创建完成");
        }
        #endregion
        #region 创建数据库、表结构、数据模型 相关
        /// <summary>
        /// 从Sqlserver 获取模型结构
        /// </summary>
        public static Tables FindAllTables(IDatabaseProvider tagertProvider, params string[] tableNames)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
            remoteDB.ModeFilePath = DAL.GetModelPath();
            remoteDB.ConnectionString = tagertProvider.ConnectionString;
            Tables tables = null;
            if (tableNames.Length > 0)
            {
                // tables = remoteDB.FindAllModelTableSchema(tableNames.ToList());
                tables = remoteDB.FindAllModelTableSchema(tableNames.ToList(), tagertProvider.DbConnection);
            }
            else
            {
                // tables = remoteDB.FindAllModelTableSchema();
                tables = remoteDB.FindAllModelTableSchema(tagertProvider.DbConnection);
            }
            stopwatch.Stop();
            Console.WriteLine("查询表结构耗时：" + stopwatch.ElapsedMilliseconds + "毫秒");
            return tables;
        }

        /// <summary>
        ///创建表结构（仅结构）； 从模型文件中取出模型表结构和索引；向目标数据库（tagertProvider）中创建表结构；
        /// </summary>
        /// <param name="modelTableName">模型表</param>
        /// <param name="tagertProvider">目标连接</param>
        /// <returns></returns>
        public static bool CreatTableSchema(string modelTableName, IDatabaseProvider tagertProvider)
        {
            lock (_tableLocker)
            {
                var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
                remoteDB.ModeFilePath = DAL.GetModelPath();
                remoteDB.ConnectionString = tagertProvider.ConnectionString;
                var conn = tagertProvider.DbConnection;
                var tran = tagertProvider.Transaction;
                bool isSuccess = remoteDB.CreatTableSchema(modelTableName, tagertProvider.TableSuffix ?? "", tagertProvider.DatabaseName, tagertProvider.Schema, tagertProvider.DbConnection, tagertProvider.Transaction);

                return isSuccess;
            }

        }
        /// <summary>
        /// 初始化基础数据（如 省市区、字典、配置等）
        /// </summary>
        public static bool FullDBInitData(List<ModelInitData> modelInitDatas, IDatabaseProvider tagertProvider)
        {

            var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
            remoteDB.ModeFilePath = DAL.GetModelPath();
            remoteDB.ConnectionString = tagertProvider.ConnectionString;
            bool isSuccess = remoteDB.FullDBInitData(modelInitDatas, tagertProvider.DbConnection, tagertProvider.Transaction);

            return isSuccess;
        }
        /// <summary>
        /// 创建数据库架构（仅数据库结构）
        /// </summary>
        /// <param name="dbFileDir">db(如MSSQL的mdf)物理文件所在目录 例 D:\DataBaseBack</param>
        /// <param name="dataBaseName">数据库名</param>
        /// <param name="tagertProvider"></param>
        /// <returns></returns>
        public static bool CreateDataBaseSchema(string dbFileDir, string dataBaseName, IDatabaseProvider tagertProvider)
        {
            lock (_databaseLocker)
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
                remoteDB.ModeFilePath = DAL.GetModelPath();
                remoteDB.ConnectionString = tagertProvider.ConnectionString;
                bool isSuccess = remoteDB.CreateDataBaseSchema(dbFileDir, dataBaseName, tagertProvider.DbConnection);
                stopwatch.Stop();
                Console.WriteLine("创建数据库结构,耗时：" + stopwatch.ElapsedMilliseconds + "毫秒");
                return isSuccess;
            }

        }
        /// <summary>
        /// 创建模型文件(这里使用sqlite作为模型文件)
        /// </summary>
        /// <param name="tagertProvider"></param>
        public static void CreateModelFileSchema(IDatabaseProvider tagertProvider)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
            remoteDB.ModeFilePath = DAL.GetModelPath();
            remoteDB.ConnectionString = tagertProvider.ConnectionString;
            remoteDB.CreateModelSchema(tagertProvider.DbConnection, tagertProvider.Transaction);
            stopwatch.Stop();
            Console.WriteLine("创建模型文件,耗时：" + stopwatch.ElapsedMilliseconds + "毫秒");
        }
        public static void FullModelFileSchema(Tables tables, IDatabaseProvider tagertProvider)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
            remoteDB.ModeFilePath = DAL.GetModelPath();
            remoteDB.ConnectionString = tagertProvider.ConnectionString;
            remoteDB.CreateModelFile(tables, tagertProvider.DbConnection, tagertProvider.Transaction);
            stopwatch.Stop();
            Console.WriteLine("填充模型文件数据,耗时：" + stopwatch.ElapsedMilliseconds + "毫秒");
        }

        /// <summary>
        /// 获取所有业务表名
        /// </summary>
        /// <returns></returns>
        public static List<string> FindAllModeTableNames(IDatabaseProvider tagertProvider)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
            remoteDB.ModeFilePath = DAL.GetModelPath();
            remoteDB.ConnectionString = tagertProvider.ConnectionString;
            var list = remoteDB.FindAllModeTableNames(tagertProvider.DbConnection, tagertProvider.Transaction);
            stopwatch.Stop();
            Console.WriteLine("获取所有业务表名：" + stopwatch.ElapsedMilliseconds + "毫秒");
            return list;
        }
        #endregion
        public static List<ModelInitData> FindBeatchInsertSql<T>(List<T> datas, IDatabaseProvider tagertProvider)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var remoteDB = DBMangerFactory.Create(tagertProvider.DBType);
            remoteDB.ModeFilePath = DAL.GetModelPath();
            remoteDB.ConnectionString = tagertProvider.ConnectionString;
            Type type = typeof(T);

            PropertyInfo[] fields = type.GetProperties();
            string data_Fields = string.Join(",", fields.Select(s => s.Name));
            Dictionary<string, Type> fieldDic = new Dictionary<string, Type>();
            foreach (PropertyInfo itemPropertyInfo in fields)
            {
                fieldDic[itemPropertyInfo.Name] = itemPropertyInfo.PropertyType;
            }
            Snowflake snowflake = new Snowflake();
            string fullTableName = type.Name;
            List<ModelInitData> modelInitDatas = new List<ModelInitData>();
            var dic = BatchHelper.ReturnBeatch<T>(datas, 1000);
            foreach (var item in dic)
            {
                long id = snowflake.NewId();
                DataTable dataTable = DataTableHelper.ListToTable(item.Value);
                string sql = remoteDB.GetBeatchInsertSql(dataTable, fieldDic, fullTableName, data_Fields);
                modelInitDatas.Add(new ModelInitData
                {
                    Id = id,
                    DataFields = sql
                });
            }
            stopwatch.Stop();
            Console.WriteLine("获取所有业务表名：" + stopwatch.ElapsedMilliseconds + "毫秒");
            return modelInitDatas;
        }


    }
}
